#pragma once
#include <iostream>
#include <fstream>
#include <cstring>

namespace ys
{
    // 获取系统时间
    void LocalTime(char *stime, const int timetvl = 0)
    {
        if (stime == nullptr)
            return;
        time_t timer;
        time(&timer); // 获取距离1970年1月1日0时0分0秒到当前的秒数
        timer += timetvl;

        // 转化为日历时间
        struct tm *now_time = localtime(&timer);
        now_time->tm_year += 1900;
        now_time->tm_mon += 1;

        // 存进 stime 格式"yyyy-mm-dd hh:mi:ss" 共19位
        snprintf(stime, 20, "%04u-%02u-%02u %02u:%02u:%02u",
                 now_time->tm_year, now_time->tm_mon, now_time->tm_mday,
                 now_time->tm_hour, now_time->tm_min, now_time->tm_sec);

        return;
    }

    // 日志文件操作类
    class LogFile
    {
    public:
        std::ofstream m_os;            // 流对象
        std::string m_filename;        // 日志文件名, 建议采用绝对路径
        std::ios::openmode m_openmode; // 日志文件打开方式, 缺省值为 append
        bool m_bEnbuffer;              // 写日志时是否启用缓冲机制, 缺省不启用
        size_t m_MaxLogSize;           // 最大入值文件的大小, 单位 MB, 缺省100MB
        bool m_bBackup;                // 是否自动切换, 当文件大小超过m_MaxLogSize 将自动切换, 缺省启用

        //构造和析构函数
        LogFile(const size_t MaxLogSize = 100)
            : m_bBackup(true), m_bEnbuffer(false), m_MaxLogSize(MaxLogSize)
        {
            // 最小是 10MB
            if (m_MaxLogSize < 10)
            {
                m_MaxLogSize = 10;
            }
        }
        ~LogFile()
        {
            Close();
        }

        // 打开日志文件
        bool Open(const char *filename, std::ios::openmode openmode = std::ios::app, bool bBackup = true, bool bEnbuffer = false)
        {
            // 如果上次打开的文件还没关闭
            Close();

            m_filename.assign(filename);
            m_openmode = openmode;
            m_bBackup = bBackup;
            m_bEnbuffer = bEnbuffer;

            m_os.open(m_filename, m_openmode); // 打开文件
            if (m_os.is_open())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        // 把内容写到日志文件, 包含时间(可变参数函数模板, 不要分文件实现)
        template <class... Args>
        bool Write(const Args &...args)
        {
            if (!m_os.is_open())
                return false;

            // 获取系统时间
            char strLocalTime[21];
            memset(strLocalTime, 0, sizeof(strLocalTime));
            LocalTime(strLocalTime);
            m_os << strLocalTime << " "; // 写入时间

            // 递归写入可变参数
            Fprint(args...);

            if (m_bEnbuffer == false)
                m_os << std::endl;
            return true;
        }
        // 关闭日志文件
        void Close()
        {
            // 关闭文件
            if (m_os.is_open())
            {
                m_os.close();
            }
            m_filename.clear();
            m_openmode = std::ios::app;
            m_bBackup = true;
            m_bEnbuffer = false;
        }

    private:
        // 实现可变参数调用打印
        template <class T>
        bool Fprint(const T &t)
        {
            if (!m_os.is_open())
                return false;
            m_os << t;
            return true;
        }

        template <class T, class... Args>
        bool Fprint(const T &t, const Args &...rest)
        {
            if (!m_os.is_open())
                return false;
            m_os << t << " ";
            Fprint(rest...); // 递归调用
            return true;
        }
    };
}